home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lpc / cmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-23  |  19.7 KB  |  972 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)cmds.c    5.3 (Berkeley) 5/5/88";
  15. #endif /* not lint */
  16.  
  17. /*
  18.  * lpc -- line printer control program -- commands:
  19.  */
  20.  
  21. #include "lp.h"
  22. #include <sys/time.h>
  23.  
  24. /*
  25.  * kill an existing daemon and disable printing.
  26.  */
  27. Abort(argc, argv)
  28.     char *argv[];
  29. {
  30.     register int c, status;
  31.     register char *cp1, *cp2;
  32.     char prbuf[100];
  33.  
  34.     if (argc == 1) {
  35.         printf("Usage: abort {all | printer ...}\n");
  36.         return;
  37.     }
  38.     if (argc == 2 && !strcmp(argv[1], "all")) {
  39.         printer = prbuf;
  40.         while (getprent(line) > 0) {
  41.             cp1 = prbuf;
  42.             cp2 = line;
  43.             while ((c = *cp2++) && c != '|' && c != ':')
  44.                 *cp1++ = c;
  45.             *cp1 = '\0';
  46.             abortpr(1);
  47.         }
  48.         return;
  49.     }
  50.     while (--argc) {
  51.         printer = *++argv;
  52.         if ((status = pgetent(line, printer)) < 0) {
  53.             printf("cannot open printer description file\n");
  54.             continue;
  55.         } else if (status == 0) {
  56.             printf("unknown printer %s\n", printer);
  57.             continue;
  58.         }
  59.         abortpr(1);
  60.     }
  61. }
  62.  
  63. abortpr(dis)
  64. {
  65.     register FILE *fp;
  66.     struct stat stbuf;
  67.     int pid, fd;
  68.  
  69.     bp = pbuf;
  70.     if ((SD = pgetstr("sd", &bp)) == NULL)
  71.         SD = DEFSPOOL;
  72.     if ((LO = pgetstr("lo", &bp)) == NULL)
  73.         LO = DEFLOCK;
  74.     (void) sprintf(line, "%s/%s", SD, LO);
  75.     printf("%s:\n", printer);
  76.  
  77.     /*
  78.      * Turn on the owner execute bit of the lock file to disable printing.
  79.      */
  80.     if (dis) {
  81.         if (stat(line, &stbuf) >= 0) {
  82.             if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
  83.                 printf("\tcannot disable printing\n");
  84.             else
  85.                 printf("\tprinting disabled\n");
  86.         } else if (errno == ENOENT) {
  87.             if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
  88.                 printf("\tcannot create lock file\n");
  89.             else {
  90.                 (void) close(fd);
  91.                 printf("\tprinting disabled\n");
  92.                 printf("\tno daemon to abort\n");
  93.             }
  94.             return;
  95.         } else {
  96.             printf("\tcannot stat lock file\n");
  97.             return;
  98.         }
  99.     }
  100.     /*
  101.      * Kill the current daemon to stop printing now.
  102.      */
  103.     if ((fp = fopen(line, "r")) == NULL) {
  104.         printf("\tcannot open lock file\n");
  105.         return;
  106.     }
  107.     if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
  108.         (void) fclose(fp);    /* unlocks as well */
  109.         printf("\tno daemon to abort\n");
  110.         return;
  111.     }
  112.     (void) fclose(fp);
  113. #ifdef sprite
  114.     /*
  115.      * sprite process id's are always printed in hex
  116.      */
  117.     if (kill(pid = atoi(line), SIGTERM) < 0)
  118.         printf("\tWarning: daemon (pid 0x%x) not killed\n", pid);
  119.     else
  120.         printf("\tdaemon (pid 0x%x) killed\n", pid);
  121. #else
  122.     if (kill(pid = atoi(line), SIGTERM) < 0)
  123.         printf("\tWarning: daemon (pid %d) not killed\n", pid);
  124.     else
  125.         printf("\tdaemon (pid %d) killed\n", pid);
  126. #endif
  127. }
  128.  
  129. /*
  130.  * Remove all spool files and temporaries from the spooling area.
  131.  */
  132. clean(argc, argv)
  133.     char *argv[];
  134. {
  135.     register int c, status;
  136.     register char *cp1, *cp2;
  137.     char prbuf[100];
  138.  
  139.     if (argc == 1) {
  140.         printf("Usage: clean {all | printer ...}\n");
  141.         return;
  142.     }
  143.     if (argc == 2 && !strcmp(argv[1], "all")) {
  144.         printer = prbuf;
  145.         while (getprent(line) > 0) {
  146.             cp1 = prbuf;
  147.             cp2 = line;
  148.             while ((c = *cp2++) && c != '|' && c != ':')
  149.                 *cp1++ = c;
  150.             *cp1 = '\0';
  151.             cleanpr();
  152.         }
  153.         return;
  154.     }
  155.     while (--argc) {
  156.         printer = *++argv;
  157.         if ((status = pgetent(line, printer)) < 0) {
  158.             printf("cannot open printer description file\n");
  159.             continue;
  160.         } else if (status == 0) {
  161.             printf("unknown printer %s\n", printer);
  162.             continue;
  163.         }
  164.         cleanpr();
  165.     }
  166. }
  167.  
  168. fileSelect(d)
  169. struct direct *d;
  170. {
  171.     int c = d->d_name[0];
  172.  
  173.     if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
  174.         return(1);
  175.     return(0);
  176. }
  177.  
  178. /*
  179.  * Comparison routine for scandir. Sort by job number and machine, then
  180.  * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
  181.  */
  182. sortq(d1, d2)
  183. struct direct **d1, **d2;
  184. {
  185.     int c1, c2;
  186.  
  187.     if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))
  188.         return(c1);
  189.     c1 = (*d1)->d_name[0];
  190.     c2 = (*d2)->d_name[0];
  191.     if (c1 == c2)
  192.         return((*d1)->d_name[2] - (*d2)->d_name[2]);
  193.     if (c1 == 'c')
  194.         return(-1);
  195.     if (c1 == 'd' || c2 == 'c')
  196.         return(1);
  197.     return(-1);
  198. }
  199.  
  200. /*
  201.  * Remove incomplete jobs from spooling area.
  202.  */
  203. cleanpr()
  204. {
  205.     register int i, n;
  206.     register char *cp, *cp1, *lp;
  207.     struct direct **queue;
  208.     int nitems;
  209.  
  210.     bp = pbuf;
  211.     if ((SD = pgetstr("sd", &bp)) == NULL)
  212.         SD = DEFSPOOL;
  213.     printf("%s:\n", printer);
  214.  
  215.     for (lp = line, cp = SD; *lp++ = *cp++; )
  216.         ;
  217.     lp[-1] = '/';
  218.  
  219.     nitems = scandir(SD, &queue, fileSelect, sortq);
  220.     if (nitems < 0) {
  221.         printf("\tcannot examine spool directory\n");
  222.         return;
  223.     }
  224.     if (nitems == 0)
  225.         return;
  226.     i = 0;
  227.     do {
  228.         cp = queue[i]->d_name;
  229.         if (*cp == 'c') {
  230.             n = 0;
  231.             while (i + 1 < nitems) {
  232.                 cp1 = queue[i + 1]->d_name;
  233.                 if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
  234.                     break;
  235.                 i++;
  236.                 n++;
  237.             }
  238.             if (n == 0) {
  239.                 strcpy(lp, cp);
  240.                 unlinkf(line);
  241.             }
  242.         } else {
  243.             /*
  244.              * Must be a df with no cf (otherwise, it would have
  245.              * been skipped above) or a tf file (which can always
  246.              * be removed).
  247.              */
  248.             strcpy(lp, cp);
  249.             unlinkf(line);
  250.         }
  251.          } while (++i < nitems);
  252. }
  253.  
  254. unlinkf(name)
  255.     char    *name;
  256. {
  257.     if (unlink(name) < 0)
  258.         printf("\tcannot remove %s\n", name);
  259.     else
  260.         printf("\tremoved %s\n", name);
  261. }
  262.  
  263. /*
  264.  * Enable queuing to the printer (allow lpr's).
  265.  */
  266. enable(argc, argv)
  267.     char *argv[];
  268. {
  269.     register int c, status;
  270.     register char *cp1, *cp2;
  271.     char prbuf[100];
  272.  
  273.     if (argc == 1) {
  274.         printf("Usage: enable {all | printer ...}\n");
  275.         return;
  276.     }
  277.     if (argc == 2 && !strcmp(argv[1], "all")) {
  278.         printer = prbuf;
  279.         while (getprent(line) > 0) {
  280.             cp1 = prbuf;
  281.             cp2 = line;
  282.             while ((c = *cp2++) && c != '|' && c != ':')
  283.                 *cp1++ = c;
  284.             *cp1 = '\0';
  285.             enablepr();
  286.         }
  287.         return;
  288.     }
  289.     while (--argc) {
  290.         printer = *++argv;
  291.         if ((status = pgetent(line, printer)) < 0) {
  292.             printf("cannot open printer description file\n");
  293.             continue;
  294.         } else if (status == 0) {
  295.             printf("unknown printer %s\n", printer);
  296.             continue;
  297.         }
  298.         enablepr();
  299.     }
  300. }
  301.  
  302. enablepr()
  303. {
  304.     struct stat stbuf;
  305.  
  306.     bp = pbuf;
  307.     if ((SD = pgetstr("sd", &bp)) == NULL)
  308.         SD = DEFSPOOL;
  309.     if ((LO = pgetstr("lo", &bp)) == NULL)
  310.         LO = DEFLOCK;
  311.     (void) sprintf(line, "%s/%s", SD, LO);
  312.     printf("%s:\n", printer);
  313.  
  314.     /*
  315.      * Turn off the group execute bit of the lock file to enable queuing.
  316.      */
  317.     if (stat(line, &stbuf) >= 0) {
  318.         if (chmod(line, stbuf.st_mode & 0767) < 0)
  319.             printf("\tcannot enable queuing\n");
  320.         else
  321.             printf("\tqueuing enabled\n");
  322.     }
  323. }
  324.  
  325. /*
  326.  * Disable queuing.
  327.  */
  328. disable(argc, argv)
  329.     char *argv[];
  330. {
  331.     register int c, status;
  332.     register char *cp1, *cp2;
  333.     char prbuf[100];
  334.  
  335.     if (argc == 1) {
  336.         printf("Usage: disable {all | printer ...}\n");
  337.         return;
  338.     }
  339.     if (argc == 2 && !strcmp(argv[1], "all")) {
  340.         printer = prbuf;
  341.         while (getprent(line) > 0) {
  342.             cp1 = prbuf;
  343.             cp2 = line;
  344.             while ((c = *cp2++) && c != '|' && c != ':')
  345.                 *cp1++ = c;
  346.             *cp1 = '\0';
  347.             disablepr();
  348.         }
  349.         return;
  350.     }
  351.     while (--argc) {
  352.         printer = *++argv;
  353.         if ((status = pgetent(line, printer)) < 0) {
  354.             printf("cannot open printer description file\n");
  355.             continue;
  356.         } else if (status == 0) {
  357.             printf("unknown printer %s\n", printer);
  358.             continue;
  359.         }
  360.         disablepr();
  361.     }
  362. }
  363.  
  364. disablepr()
  365. {
  366.     register int fd;
  367.     struct stat stbuf;
  368.  
  369.     bp = pbuf;
  370.     if ((SD = pgetstr("sd", &bp)) == NULL)
  371.         SD = DEFSPOOL;
  372.     if ((LO = pgetstr("lo", &bp)) == NULL)
  373.         LO = DEFLOCK;
  374.     (void) sprintf(line, "%s/%s", SD, LO);
  375.     printf("%s:\n", printer);
  376.     /*
  377.      * Turn on the group execute bit of the lock file to disable queuing.
  378.      */
  379.     if (stat(line, &stbuf) >= 0) {
  380.         if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
  381.             printf("\tcannot disable queuing\n");
  382.         else
  383.             printf("\tqueuing disabled\n");
  384.     } else if (errno == ENOENT) {
  385.         if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
  386.             printf("\tcannot create lock file\n");
  387.         else {
  388.             (void) close(fd);
  389.             printf("\tqueuing disabled\n");
  390.         }
  391.         return;
  392.     } else
  393.         printf("\tcannot stat lock file\n");
  394. }
  395.  
  396. /*
  397.  * Disable queuing and printing and put a message into the status file
  398.  * (reason for being down).
  399.  */
  400. down(argc, argv)
  401.     char *argv[];
  402. {
  403.     register int c, status;
  404.     register char *cp1, *cp2;
  405.     char prbuf[100];
  406.  
  407.     if (argc == 1) {
  408.         printf("Usage: down {all | printer} [message ...]\n");
  409.         return;
  410.     }
  411.     if (!strcmp(argv[1], "all")) {
  412.         printer = prbuf;
  413.         while (getprent(line) > 0) {
  414.             cp1 = prbuf;
  415.             cp2 = line;
  416.             while ((c = *cp2++) && c != '|' && c != ':')
  417.                 *cp1++ = c;
  418.             *cp1 = '\0';
  419.             putmsg(argc - 2, argv + 2);
  420.         }
  421.         return;
  422.     }
  423.     printer = argv[1];
  424.     if ((status = pgetent(line, printer)) < 0) {
  425.         printf("cannot open printer description file\n");
  426.         return;
  427.     } else if (status == 0) {
  428.         printf("unknown printer %s\n", printer);
  429.         return;
  430.     }
  431.     putmsg(argc - 2, argv + 2);
  432. }
  433.  
  434. putmsg(argc, argv)
  435.     char **argv;
  436. {
  437.     register int fd;
  438.     register char *cp1, *cp2;
  439.     char buf[1024];
  440.     struct stat stbuf;
  441.  
  442.     bp = pbuf;
  443.     if ((SD = pgetstr("sd", &bp)) == NULL)
  444.         SD = DEFSPOOL;
  445.     if ((LO = pgetstr("lo", &bp)) == NULL)
  446.         LO = DEFLOCK;
  447.     if ((ST = pgetstr("st", &bp)) == NULL)
  448.         ST = DEFSTAT;
  449.     printf("%s:\n", printer);
  450.     /*
  451.      * Turn on the group execute bit of the lock file to disable queuing and
  452.      * turn on the owner execute bit of the lock file to disable printing.
  453.      */
  454.     (void) sprintf(line, "%s/%s", SD, LO);
  455.     if (stat(line, &stbuf) >= 0) {
  456.         if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
  457.             printf("\tcannot disable queuing\n");
  458.         else
  459.             printf("\tprinter and queuing disabled\n");
  460.     } else if (errno == ENOENT) {
  461.         if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
  462.             printf("\tcannot create lock file\n");
  463.         else {
  464.             (void) close(fd);
  465.             printf("\tprinter and queuing disabled\n");
  466.         }
  467.         return;
  468.     } else
  469.         printf("\tcannot stat lock file\n");
  470.     /*
  471.      * Write the message into the status file.
  472.      */
  473.     (void) sprintf(line, "%s/%s", SD, ST);
  474.     fd = open(line, O_WRONLY|O_CREAT, 0664);
  475.     if (fd < 0 || flock(fd, LOCK_EX) < 0) {
  476.         printf("\tcannot create status file\n");
  477.         return;
  478.     }
  479.     (void) ftruncate(fd, 0);
  480.     if (argc <= 0) {
  481.         (void) write(fd, "\n", 1);
  482.         (void) close(fd);
  483.         return;
  484.     }
  485.     cp1 = buf;
  486.     while (--argc >= 0) {
  487.         cp2 = *argv++;
  488.         while (*cp1++ = *cp2++)
  489.             ;
  490.         cp1[-1] = ' ';
  491.     }
  492.     cp1[-1] = '\n';
  493.     *cp1 = '\0';
  494.     (void) write(fd, buf, strlen(buf));
  495.     (void) close(fd);
  496. }
  497.  
  498. /*
  499.  * Exit lpc
  500.  */
  501. quit(argc, argv)
  502.     char *argv[];
  503. {
  504.     exit(0);
  505. }
  506.  
  507. /*
  508.  * Kill and restart the daemon.
  509.  */
  510. restart(argc, argv)
  511.     char *argv[];
  512. {
  513.     register int c, status;
  514.     register char *cp1, *cp2;
  515.     char prbuf[100];
  516.  
  517.     if (argc == 1) {
  518.         printf("Usage: restart {all | printer ...}\n");
  519.         return;
  520.     }
  521.     if (argc == 2 && !strcmp(argv[1], "all")) {
  522.         printer = prbuf;
  523.         while (getprent(line) > 0) {
  524.             cp1 = prbuf;
  525.             cp2 = line;
  526.             while ((c = *cp2++) && c != '|' && c != ':')
  527.                 *cp1++ = c;
  528.             *cp1 = '\0';
  529.             abortpr(0);
  530.             startpr(0);
  531.         }
  532.         return;
  533.     }
  534.     while (--argc) {
  535.         printer = *++argv;
  536.         if ((status = pgetent(line, printer)) < 0) {
  537.             printf("cannot open printer description file\n");
  538.             continue;
  539.         } else if (status == 0) {
  540.             printf("unknown printer %s\n", printer);
  541.             continue;
  542.         }
  543.         abortpr(0);
  544.         startpr(0);
  545.     }
  546. }
  547.  
  548. /*
  549.  * Enable printing on the specified printer and startup the daemon.
  550.  */
  551. start(argc, argv)
  552.     char *argv[];
  553. {
  554.     register int c, status;
  555.     register char *cp1, *cp2;
  556.     char prbuf[100];
  557.  
  558.     if (argc == 1) {
  559.         printf("Usage: start {all | printer ...}\n");
  560.         return;
  561.     }
  562.     if (argc == 2 && !strcmp(argv[1], "all")) {
  563.         printer = prbuf;
  564.         while (getprent(line) > 0) {
  565.             cp1 = prbuf;
  566.             cp2 = line;
  567.             while ((c = *cp2++) && c != '|' && c != ':')
  568.                 *cp1++ = c;
  569.             *cp1 = '\0';
  570.             startpr(1);
  571.         }
  572.         return;
  573.     }
  574.     while (--argc) {
  575.         printer = *++argv;
  576.         if ((status = pgetent(line, printer)) < 0) {
  577.             printf("cannot open printer description file\n");
  578.             continue;
  579.         } else if (status == 0) {
  580.             printf("unknown printer %s\n", printer);
  581.             continue;
  582.         }
  583.         startpr(1);
  584.     }
  585. }
  586.  
  587. startpr(enable)
  588. {
  589.     struct stat stbuf;
  590.  
  591.     bp = pbuf;
  592.     if ((SD = pgetstr("sd", &bp)) == NULL)
  593.         SD = DEFSPOOL;
  594.     if ((LO = pgetstr("lo", &bp)) == NULL)
  595.         LO = DEFLOCK;
  596.     (void) sprintf(line, "%s/%s", SD, LO);
  597.     printf("%s:\n", printer);
  598.  
  599.     /*
  600.      * Turn off the owner execute bit of the lock file to enable printing.
  601.      */
  602.     if (enable && stat(line, &stbuf) >= 0) {
  603.         if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
  604.             printf("\tcannot enable printing\n");
  605.         else
  606.             printf("\tprinting enabled\n");
  607.     }
  608.     if (!startdaemon(printer))
  609.         printf("\tcouldn't start daemon\n");
  610.     else
  611.         printf("\tdaemon started\n");
  612. }
  613.  
  614. /*
  615.  * Print the status of each queue listed or all the queues.
  616.  */
  617. status(argc, argv)
  618.     char *argv[];
  619. {
  620.     register int c, status;
  621.     register char *cp1, *cp2;
  622.     char prbuf[100];
  623.  
  624.     if (argc == 1) {
  625.         printer = prbuf;
  626.         while (getprent(line) > 0) {
  627.             cp1 = prbuf;
  628.             cp2 = line;
  629.             while ((c = *cp2++) && c != '|' && c != ':')
  630.                 *cp1++ = c;
  631.             *cp1 = '\0';
  632.             prstat();
  633.         }
  634.         return;
  635.     }
  636.     while (--argc) {
  637.         printer = *++argv;
  638.         if ((status = pgetent(line, printer)) < 0) {
  639.             printf("cannot open printer description file\n");
  640.             continue;
  641.         } else if (status == 0) {
  642.             printf("unknown printer %s\n", printer);
  643.             continue;
  644.         }
  645.         prstat();
  646.     }
  647. }
  648.  
  649. /*
  650.  * Print the status of the printer queue.
  651.  */
  652. prstat()
  653. {
  654.     struct stat stbuf;
  655.     register int fd, i;
  656.     register struct direct *dp;
  657.     DIR *dirp;
  658.  
  659.     bp = pbuf;
  660.     if ((SD = pgetstr("sd", &bp)) == NULL)
  661.         SD = DEFSPOOL;
  662.     if ((LO = pgetstr("lo", &bp)) == NULL)
  663.         LO = DEFLOCK;
  664.     if ((ST = pgetstr("st", &bp)) == NULL)
  665.         ST = DEFSTAT;
  666.     printf("%s:\n", printer);
  667.     (void) sprintf(line, "%s/%s", SD, LO);
  668.     if (stat(line, &stbuf) >= 0) {
  669.         printf("\tqueuing is %s\n",
  670.             (stbuf.st_mode & 010) ? "disabled" : "enabled");
  671.         printf("\tprinting is %s\n",
  672.             (stbuf.st_mode & 0100) ? "disabled" : "enabled");
  673.     } else {
  674.         printf("\tqueuing is enabled\n");
  675.         printf("\tprinting is enabled\n");
  676.     }
  677.     if ((dirp = opendir(SD)) == NULL) {
  678.         printf("\tcannot examine spool directory\n");
  679.         return;
  680.     }
  681.     i = 0;
  682.     while ((dp = readdir(dirp)) != NULL) {
  683.         if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
  684.             i++;
  685.     }
  686.     closedir(dirp);
  687.     if (i == 0)
  688.         printf("\tno entries\n");
  689.     else if (i == 1)
  690.         printf("\t1 entry in spool area\n");
  691.     else
  692.         printf("\t%d entries in spool area\n", i);
  693.     fd = open(line, O_RDONLY);
  694.     if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
  695.         (void) close(fd);    /* unlocks as well */
  696.         printf("\tno daemon present\n");
  697.         return;
  698.     }
  699.     (void) close(fd);
  700.     putchar('\t');
  701.     (void) sprintf(line, "%s/%s", SD, ST);
  702.     fd = open(line, O_RDONLY);
  703.     if (fd >= 0) {
  704.         (void) flock(fd, LOCK_SH);
  705.         while ((i = read(fd, line, sizeof(line))) > 0)
  706.             (void) fwrite(line, 1, i, stdout);
  707.         (void) close(fd);    /* unlocks as well */
  708.     }
  709. }
  710.  
  711. /*
  712.  * Stop the specified daemon after completing the current job and disable
  713.  * printing.
  714.  */
  715. stop(argc, argv)
  716.     char *argv[];
  717. {
  718.     register int c, status;
  719.     register char *cp1, *cp2;
  720.     char prbuf[100];
  721.  
  722.     if (argc == 1) {
  723.         printf("Usage: stop {all | printer ...}\n");
  724.         return;
  725.     }
  726.     if (argc == 2 && !strcmp(argv[1], "all")) {
  727.         printer = prbuf;
  728.         while (getprent(line) > 0) {
  729.             cp1 = prbuf;
  730.             cp2 = line;
  731.             while ((c = *cp2++) && c != '|' && c != ':')
  732.                 *cp1++ = c;
  733.             *cp1 = '\0';
  734.             stoppr();
  735.         }
  736.         return;
  737.     }
  738.     while (--argc) {
  739.         printer = *++argv;
  740.         if ((status = pgetent(line, printer)) < 0) {
  741.             printf("cannot open printer description file\n");
  742.             continue;
  743.         } else if (status == 0) {
  744.             printf("unknown printer %s\n", printer);
  745.             continue;
  746.         }
  747.         stoppr();
  748.     }
  749. }
  750.  
  751. stoppr()
  752. {
  753.     register int fd;
  754.     struct stat stbuf;
  755.  
  756.     bp = pbuf;
  757.     if ((SD = pgetstr("sd", &bp)) == NULL)
  758.         SD = DEFSPOOL;
  759.     if ((LO = pgetstr("lo", &bp)) == NULL)
  760.         LO = DEFLOCK;
  761.     (void) sprintf(line, "%s/%s", SD, LO);
  762.     printf("%s:\n", printer);
  763.  
  764.     /*
  765.      * Turn on the owner execute bit of the lock file to disable printing.
  766.      */
  767.     if (stat(line, &stbuf) >= 0) {
  768.         if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
  769.             printf("\tcannot disable printing\n");
  770.         else
  771.             printf("\tprinting disabled\n");
  772.     } else if (errno == ENOENT) {
  773.         if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
  774.             printf("\tcannot create lock file\n");
  775.         else {
  776.             (void) close(fd);
  777.             printf("\tprinting disabled\n");
  778.         }
  779.     } else
  780.         printf("\tcannot stat lock file\n");
  781. }
  782.  
  783. struct    queue **queue;
  784. int    nitems;
  785. time_t    mtime;
  786.  
  787. /*
  788.  * Put the specified jobs at the top of printer queue.
  789.  */
  790. topq(argc, argv)
  791.     char *argv[];
  792. {
  793.     register int n, i;
  794.     struct stat stbuf;
  795.     register char *cfname;
  796.     int status, changed;
  797.  
  798.     if (argc < 3) {
  799.         printf("Usage: topq printer [jobnum ...] [user ...]\n");
  800.         return;
  801.     }
  802.  
  803.     --argc;
  804.     printer = *++argv;
  805.     status = pgetent(line, printer);
  806.     if (status < 0) {
  807.         printf("cannot open printer description file\n");
  808.         return;
  809.     } else if (status == 0) {
  810.         printf("%s: unknown printer\n", printer);
  811.         return;
  812.     }
  813.     bp = pbuf;
  814.     if ((SD = pgetstr("sd", &bp)) == NULL)
  815.         SD = DEFSPOOL;
  816.     if ((LO = pgetstr("lo", &bp)) == NULL)
  817.         LO = DEFLOCK;
  818.     printf("%s:\n", printer);
  819.  
  820.     if (chdir(SD) < 0) {
  821.         printf("\tcannot chdir to %s\n", SD);
  822.         return;
  823.     }
  824.     nitems = getq(&queue);
  825.     if (nitems == 0)
  826.         return;
  827.     changed = 0;
  828.     mtime = queue[0]->q_time;
  829.     for (i = argc; --i; ) {
  830.         if (doarg(argv[i]) == 0) {
  831.             printf("\tjob %s is not in the queue\n", argv[i]);
  832.             continue;
  833.         } else
  834.             changed++;
  835.     }
  836.     for (i = 0; i < nitems; i++)
  837.         free(queue[i]);
  838.     free(queue);
  839.     if (!changed) {
  840.         printf("\tqueue order unchanged\n");
  841.         return;
  842.     }
  843.     /*
  844.      * Turn on the public execute bit of the lock file to
  845.      * get lpd to rebuild the queue after the current job.
  846.      */
  847.     if (changed && stat(LO, &stbuf) >= 0)
  848.         (void) chmod(LO, (stbuf.st_mode & 0777) | 01);
  849.  
  850. /*
  851.  * Reposition the job by changing the modification time of
  852.  * the control file.
  853.  */
  854. touch(q)
  855.     struct queue *q;
  856. {
  857.     struct timeval tvp[2];
  858.  
  859.     tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
  860.     tvp[0].tv_usec = tvp[1].tv_usec = 0;
  861.     return(utimes(q->q_name, tvp));
  862. }
  863.  
  864. /*
  865.  * Checks if specified job name is in the printer's queue.
  866.  * Returns:  negative (-1) if argument name is not in the queue.
  867.  */
  868. doarg(job)
  869.     char *job;
  870. {
  871.     register struct queue **qq;
  872.     register int jobnum, n;
  873.     register char *cp, *machine;
  874.     int cnt = 0;
  875.     FILE *fp;
  876.  
  877.     /*
  878.      * Look for a job item consisting of system name, colon, number 
  879.      * (example: ucbarpa:114)  
  880.      */
  881.     if ((cp = index(job, ':')) != NULL) {
  882.         machine = job;
  883.         *cp++ = '\0';
  884.         job = cp;
  885.     } else
  886.         machine = NULL;
  887.  
  888.     /*
  889.      * Check for job specified by number (example: 112 or 235ucbarpa).
  890.      */
  891.     if (isdigit(*job)) {
  892.         jobnum = 0;
  893.         do
  894.             jobnum = jobnum * 10 + (*job++ - '0');
  895.         while (isdigit(*job));
  896.         for (qq = queue + nitems; --qq >= queue; ) {
  897.             n = 0;
  898.             for (cp = (*qq)->q_name+3; isdigit(*cp); )
  899.                 n = n * 10 + (*cp++ - '0');
  900.             if (jobnum != n)
  901.                 continue;
  902.             if (*job && strcmp(job, cp) != 0)
  903.                 continue;
  904.             if (machine != NULL && strcmp(machine, cp) != 0)
  905.                 continue;
  906.             if (touch(*qq) == 0) {
  907.                 printf("\tmoved %s\n", (*qq)->q_name);
  908.                 cnt++;
  909.             }
  910.         }
  911.         return(cnt);
  912.     }
  913.     /*
  914.      * Process item consisting of owner's name (example: henry).
  915.      */
  916.     for (qq = queue + nitems; --qq >= queue; ) {
  917.         if ((fp = fopen((*qq)->q_name, "r")) == NULL)
  918.             continue;
  919.         while (getline(fp) > 0)
  920.             if (line[0] == 'P')
  921.                 break;
  922.         (void) fclose(fp);
  923.         if (line[0] != 'P' || strcmp(job, line+1) != 0)
  924.             continue;
  925.         if (touch(*qq) == 0) {
  926.             printf("\tmoved %s\n", (*qq)->q_name);
  927.             cnt++;
  928.         }
  929.     }
  930.     return(cnt);
  931. }
  932.  
  933. /*
  934.  * Enable everything and start printer (undo `down').
  935.  */
  936. up(argc, argv)
  937.     char *argv[];
  938. {
  939.     register int c, status;
  940.     register char *cp1, *cp2;
  941.     char prbuf[100];
  942.  
  943.     if (argc == 1) {
  944.         printf("Usage: up {all | printer ...}\n");
  945.         return;
  946.     }
  947.     if (argc == 2 && !strcmp(argv[1], "all")) {
  948.         printer = prbuf;
  949.         while (getprent(line) > 0) {
  950.             cp1 = prbuf;
  951.             cp2 = line;
  952.             while ((c = *cp2++) && c != '|' && c != ':')
  953.                 *cp1++ = c;
  954.             *cp1 = '\0';
  955.             startpr(2);
  956.         }
  957.         return;
  958.     }
  959.     while (--argc) {
  960.         printer = *++argv;
  961.         if ((status = pgetent(line, printer)) < 0) {
  962.             printf("cannot open printer description file\n");
  963.             continue;
  964.         } else if (status == 0) {
  965.             printf("unknown printer %s\n", printer);
  966.             continue;
  967.         }
  968.         startpr(2);
  969.     }
  970. }
  971.